package com.example.gokuplayalong.bases.security;


import com.example.gokuplayalong.bases.base.AppParams;
import com.example.gokuplayalong.bases.base.ExceptionHandler;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Base64;

import static java.lang.Math.abs;

public class Communication {
    public int code = 0;
    private final int VALID_TIME_MAX = 1000 * 10;
    private String AesKey = "";
    private String RSAAesKey = "";
    private String AESMsg = "";
    private String TimeStamp = "";
    private String md5Key = "faidojgadsklmgalsg094gmrgj4";
    private String md5rand = "";
    private String md5Sign = "";

    public Communication() {
        File f = new File(AppParams.getInstance().securityPathLinux);
        if (!f.exists()) {
            if (f.mkdirs()) System.out.println("创建成功!");
            else System.out.println("创建失败!");
        }
    }

    public String MessageEncrypt(String message) {

        try {
            //1.生成AES密钥
            if (AesKey == null || AesKey.equals("")) {
                AesKey = AESEncrypt.getKey();
            }
            //2.使用ServerRSA公钥 对AES密钥进行加密
            RSAAesKey = RSAEncrypt.encryptByPublicKey(AesKey, RSAEncrypt.ClientPublicKey);
            //3.使用AES密钥对消息明文进行加密
            AESMsg = AESEncrypt.encrypt(message, AesKey);
            //4.获取当前时间戳
            TimeStamp = String.valueOf(System.currentTimeMillis());
            //5.生成随机字符串
            md5rand = AESEncrypt.getKey();
            //6.将参数密文、时间戳、随机字符串和AES密钥密文进行MD5计算得到md5值；
            //AESMsg TimeStamp md5rand RSAesKey md5Key
            String md5in = RSAAesKey + "." + AESMsg + "." + TimeStamp + "." + md5rand;
            //7.计算MD5的数字签名
            String md5 = MD5Util.string2MD5(md5in + md5Key);
            md5Sign = RSAEncrypt.sign(md5.getBytes(), Base64.getDecoder().decode(RSAEncrypt.ServerPrivateKey), "RSA");
            //8.拼接结果
            if (RSAAesKey == null || AESMsg == null || TimeStamp == null || md5rand == null || md5Sign == null) {
                code = 4;
                return "空值，无效参数";
            }
            return md5in + "." + md5Sign;

        } catch (Exception e) {
            ExceptionHandler.saveException(Thread.currentThread().getStackTrace()[1].getClassName() + Thread.currentThread().getStackTrace()[1].getMethodName() + Thread.currentThread().getStackTrace()[1].getLineNumber(), e);
            return "";
        }
    }

    public String MessageDecrypt(String message) {
        code = 0;
        try {
            String path = "";

            String[] str = message.split("\\.");
            if (str.length != 5) {
                code = -1;
                return "无效请求" + code;
            }
            RSAAesKey = str[0];
            AESMsg = str[1];
            TimeStamp = str[2].trim();
            md5rand = str[3];
            md5Sign = str[4];
            //1.验证时间有效性
            if (!TimeStamp.equalsIgnoreCase("") && abs(System.currentTimeMillis() - Long.parseLong(TimeStamp)) > VALID_TIME_MAX) {
                code = 1;
                return "无效请求" + code;
            }


            //2.验证md5rand唯一性
            if (AppParams.getInstance().Platform == "linux") {
                path = AppParams.getInstance().securityPathLinux + "/md5rand";
            }
            else {
                path = AppParams.getInstance().WindowHomeDir + "\\security\\md5rand";
            }

            File f = new File(path);
            if (!f.exists()) {
                if (f.createNewFile()) System.out.println("创建成功!");
                else System.out.println("创建失败!");

            }


            if (f.exists()) {
                FileInputStream in = new FileInputStream(f);
                byte[] buffer = new byte[in.available()];
                in.read(buffer);
                in.close();
                String md5randin = new String(buffer);
                String[] md5randList = md5randin.split("\\.");
                for (String s : md5randList) {
                    if (s.equals(md5rand)) {
                        code = 2;
                        return "无效请求" + code;
                    }
                }


                FileOutputStream out;
                if (md5randList.length > 100) {
                    out = new FileOutputStream(f.getAbsoluteFile(), false);
                }
                else {
                    out = new FileOutputStream(f.getAbsoluteFile(), true);
                }
                out.write((md5rand + ".").getBytes());
                out.close();
            }
            //3.验证签名有效性
            String md5in = RSAAesKey + "." + AESMsg + "." + TimeStamp + "." + md5rand;
            String md5 = MD5Util.string2MD5(md5in + md5Key);
            boolean verify = RSAEncrypt.verify(md5.getBytes(), Base64.getDecoder().decode(md5Sign.replaceAll("\r|\n", "")), Base64.getDecoder().decode(RSAEncrypt.ClientPublicKey), "RSA");
            if (!verify) {
                code = 3;
                return "无效请求" + code;
            }

            //4.APP解密AES密钥密文
            AesKey = RSAEncrypt.decryptByPrivateKey(RSAAesKey, RSAEncrypt.ServerPrivateKey);
            //5.解密参数密文
            AESMsg = AESEncrypt.decrypt(AESMsg, AesKey);

        } catch (Exception e) {
            ExceptionHandler.saveException(Thread.currentThread().getStackTrace()[1].getClassName() + Thread.currentThread().getStackTrace()[1].getMethodName() + Thread.currentThread().getStackTrace()[1].getLineNumber(), e);
        }
        return AESMsg;
    }

    public int getCode() {
        return code;
    }
}